const express = require('express')
const app = express();
app.listen(8080, () => {
    console.log('8080 端口服务器已启动 http://127.0.0.1:8080')
})
app.use(express.json())
//app.use(express.urlencoded({ extended: false }))
const parser = require('body-parser')
app.use(parser.urlencoded({ extended: false }))
//链接数据库
const db = require('../../SQL语句/3.1安装配置mysql模块')


//JWT身份认证认证机制
//总结:用户的信息通过Token字符串的形式，保存在客户端浏览器中。服务器通过还原Token字符串的形式来认证用户的身份。
//JWT通常由三部分组成，分别是 Header(头部)、Payload(有效荷载)、Signature(签名)
//三者之间使用英文的“”分隔，格式如下:
//Header.Payload.Signature

//JWT的使用方式
//此后，客户端每次与服务器通信，都要带上这个JWT的字符串，从而进行身份认证。推荐的做法是把JWT放在HTTP请求头的Authorization字段中，格式如下:
//Authorization: Bearer < token >

//jsonwebtoken用于生成JWT字符串
//express - jwt用于将JWT字符串解析还原成JSON对象

//导入用于生成JwT字符串的包 加密
const jwt = require('jsonwebtoken')
//导入用于将客户端发误过来的JwT字符串，解析还原成JSON对象的包 解密
const expressJWT = require("express-jwt");
//secret密钥的本质:就是一个字符串
const secretKey = 'zouyangguang'

//注意:只要配置成功了express-jwt 这个中间件，就可以把解析出来的用户信息，挂载到req.user属性上
app.use(expressJWT({ secret: secretKey }).unless({ path: [/^\/api\//] }))

//存储Session 数据
app.post('/api/login', (req, res) => {
    //待执行的SQL语句，其中英文的?表示占位符
    const sqlStr = `SELECT * FROM users WHERE username=? and password=?`
    //查看数据库里的账号和密码是否存在
    db.query(sqlStr, [req.body.user, req.body.password], (err, results) => {
        //查询数据失败
        if (err) return console.log(err.message)
        //查询数据成功

        //注意:如果执行的是 select查询语句，则执行的结果是数组
        //判断 results里是否有数据
        if (results.length != 0) {
            //登陆成功
            //在登录成功之后，调用jwt.sign()方法生成JWT字符串。并通过 token属性发送给客户端
            //参数1: 用户的信息对象
            //参数2: 加密的秘钥
            //参数3: 配置对象，可以配置当前token的有效期
            //不要加密密码
            const tokenStr = jwt.sign({ username: req.body.user }, secretKey, { expiresIn: '60s' })
            res.send({ status: 0, msg: '登录成功', token: tokenStr })
            console.log(results)
        } else {
            return res.send({ status: 1, msg: '登录失败', ll: req.body })
        }
    })
})
//这是—个有权限的 API 接口
//在 Authorization 请求头 Bearer
app.get('/admin/getinfo', (req, res) => {
    //使用req.user 获取用户信息，并使用data属性将用户信息发送给客户端
    console.log(req.user)
    res.send({
        user: req.user //′要发送给客户端的用户信息
    })
})

//当使用express-jwt解析Token字符串时，如果客户端发送过来的Token字符串过期或不合法，
//会产生一个解析失败的错误，影响项目的正常运行。我们可以通过 Express 的错误中间件，
//捕获这个错误并进行相关的处理，示例代码如下:
//使用全局错误处理中间件，捕获解析JWT 失败后产生的错误
app.use((err, req, res, next) => {
    //这次错误是由token解析失败导致的
    if (err.name == 'UnauthorizedError') {
        return res.send({
            status: 401,
            message: 'token 密钥已过期'
        })
    }
    res.send({
        status: 500,
        message: '未知错误服务器即将爆炸'
    })
})

//定要在路由之前，配置 cors这个中间件,从而解决接口跨域的问题
const cors = require('cors')
app.use(cors())

